// go并发
package main

import (
	"fmt"
	"time"
)

/*
Go 语言支持并发，我们只需要通过 go 关键字来开启 goroutine 即可。
goroutine 是轻量级线程，goroutine 的调度是由 Golang 运行时进行管理的。
goroutine 语法格式：
go 函数名( 参数列表 )
如: go f(x, y, z)
*/
func say(s string) {
	for i := 0; i < 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}
func t1() {
	go say("world")
	say("hello")
}

/*
通道（channel）是用来传递数据的一个数据结构。
通道可用于两个 goroutine 之间通过传递一个指定类型的值来同步运行和通讯。操作符 <- 用于指定通道的方向，发送或接收。如果未指定方向，则为双向通道。
ch <- v    // 把 v 发送到通道 ch
v := <-ch  // 从 ch 接收数据并把值赋给 v
ch := make(chan int)
*/
func sum(s []int, c chan int) {
	sum := 0
	for _, v := range s {
		sum += v
	}
	// 把sum发送到通道c
	c <- sum
}
func t2() {
	s := []int {7, 2, 8, -9, 4, 0}

	c := make(chan int)
	go sum(s[: len(s) / 2], c)
	go sum(s[len(s) / 2:], c)
	// 从通道中接收
	x, y := <- c, <- c
	fmt.Println(x, y, x + y)
}

/*
通道可以设置缓冲区，通过 make 的第二个参数指定缓冲区大小：
ch := make(chan int, 100)
*/
func t3() {
	ch := make(chan int, 2)
	ch <- 1
	ch <- 2

	fmt.Println(<- ch)
	fmt.Println(<- ch)
}

/*
遍历通道和关闭通道
v, ok := <-ch
*/
func fibonacci(n int, c chan int) {
	x, y := 0, 1
	for i := 0; i < n; i++ {
		c <- x
		x, y = y, x + y
	}
	close(c)
}
func t4() {
	c := make(chan int, 10)
	go fibonacci(cap(c), c)
	for i := range c {
		fmt.Println(i)
	}
}
